package sy4_Creational_Pattern.builder.wuzeng;

import lombok.Data;

@Data
class Product {   //角色1：复杂产品类Product，表示被建造的对象
	private String food;
	private String drink;
}

abstract class Builder  { //角色2：抽象建造者Builder
	//产品部件构建
	public abstract void buildFood(String food);
	public abstract void buildDrink(String drink);
	//完整产品构建
	public abstract Product buildProduct();

}

class ConcreteBuilder  extends Builder  { //角色3：具体建造者类ConcreteBuilder
	//套餐名称
	private String meal;
	//部件名称
	private String food;
	private String drink;

	public ConcreteBuilder(String meal) {  //构造方法
		this.meal = meal;
		System.out.println(meal);
	}

	@Override
	public void buildFood(String food) {  //重写基类方法
		this.food=food;
	}

	@Override
	public void buildDrink(String drink) {  //重写基类方法
		this.drink=drink;
	}

	@Override
	public Product buildProduct() { //重写基类方法
		Product product = new Product();
		product.setFood(food);
		product.setDrink(drink);
		return product;  
	}
}

class Director  { //角色4：指挥者类Director，聚合Builder对象，指挥产品的建造过程
	private Builder builder;  //聚合

	public Director(Builder builder) {  //构造器注入
		this.builder = builder;
	}

	public Product construct(String food, String drink) {  //构建（装配）方法
		//调用建造者，可以使用钩子方法控制产品的建造
		builder.buildFood(food);  
		builder.buildDrink(drink);

		return builder.buildProduct();  //返回复杂产品
	}
}

public class Client { //客户端
	public static void main(String[] args) {
		//使用指挥者，客户端程序就不需要知道产品建造细节
		Director director=new Director(new ConcreteBuilder("肯德基快餐"));
		Product product = director.construct("炸鸡", "百事可乐");
		System.out.println(product);
		
		//如果不使用指挥者，客户端程序则需要知道产品建造细节
		Builder builder = new ConcreteBuilder("麦当劳快餐");
		//注释下面建造的两行代码，将输出空产品
		builder.buildFood("汉堡");  //建造
		builder.buildDrink("可口可乐");  //建造
		System.out.println(builder.buildProduct());
	}
}
